package com.eastedu.report.principal.util;

import com.deepoove.poi.data.Cells;
import com.deepoove.poi.data.MergeCellRule;
import com.deepoove.poi.data.Rows;
import com.deepoove.poi.data.Tables;
import com.eastedu.common.enums.SubjectType;
import com.eastedu.report.common.model.po.*;
import com.eastedu.report.common.util.DecimalUtil;
import com.eastedu.report.common.util.NumberFormatUtil;
import com.eastedu.report.principal.model.additional.*;
import com.eastedu.utils.ContinuousElementsUtil;
import com.google.common.collect.Lists;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 校长月报报告表格工具
 *
 * @author superman
 */
public interface ReportTableUtil {
    /**
     * 附件一：本月教师资源应用指数排名
     *
     * @param pos the pos
     * @return the teacher resource usage index rank
     */
    static List<TeacherResourceUsageIndexRank> getTeacherResourceUsageIndexRank(List<TeacherResourceUsageIndexPO> pos) {
        return pos.parallelStream()
                .map(po -> {
                    TeacherResourceUsageIndexRank rank = new TeacherResourceUsageIndexRank();
                    fillCommonRankInfo(po, rank);
                    rank.setIndex(determinedOutput(Objects.isNull(po.getResourceUseIndex()) ? null : DecimalUtil.doubleFormat(po.getResourceUseIndex(), "#0.0")));
                    return rank;
                })
                .sorted(Comparator.comparing(comparing()))
                .collect(Collectors.toList());
    }


    /**
     * 附件二： 获取教师同步备课环节资源使用个数排名
     *
     * @param pos the pos
     * @return the teacher prepare lesson usage rank
     */
    static List<TeacherPrepareLessonUsageNumberRank> getTeacherPrepareLessonUsageRank(List<TeacherTeachingActivityPrepareResourceUsageDetailPO> pos) {
        return pos.parallelStream()
                .map(po -> {
                    TeacherPrepareLessonUsageNumberRank rank = new TeacherPrepareLessonUsageNumberRank();
                    fillCommonRankInfo(po, rank);
                    rank.setTotal(determinedOutput(po.getResourceUseNumber()));

                    rank.setPrepareLessonFollowedUseNumber(determinedOutput(po.getPrepareLessonFollowedUseNumber()));
                    rank.setPrepareLessonHistoryUseNumber(determinedOutput(po.getPrepareLessonHistoryUseNumber()));
                    rank.setPrepareLessonWareFollowedUseNumber(determinedOutput(po.getPrepareLessonWareFollowedUseNumber()));
                    rank.setPrepareLessonWareHistoryUseNumber(determinedOutput(po.getPrepareLessonWareHistoryUseNumber()));
                    rank.setPrepareLessonSummaryFollowedUseNumber(determinedOutput(po.getPrepareLessonSummaryFollowedUseNumber()));
                    rank.setPrepareLessonSummaryHistoryUseNumber(determinedOutput(po.getPrepareLessonSummaryHistoryUseNumber()));

                    return rank;
                })
                .sorted(Comparator.comparing(comparing()))
                .collect(Collectors.toList());
    }

    /**
     * 附件三: 获取教师同步教学环节资源使用个数排名
     *
     * @param pos the pos
     * @return the teacher teaching usage rank
     */
    static List<TeacherTeachingUsageNumberRank> getTeacherTeachingUsageRank(List<TeacherTeachingActivityTeachingResourceUsageDetailPO> pos) {
        return pos.parallelStream()
                .map(po -> {
                    TeacherTeachingUsageNumberRank rank = new TeacherTeachingUsageNumberRank();
                    fillCommonRankInfo(po, rank);
                    rank.setTotal(determinedOutput(po.getResourceUseNumber()));
                    rank.setClassRecordFollowedUseNumber(determinedOutput(po.getClassroomRecordFollowedUseNumber()));
                    rank.setClassRecordHistoryUseNumber(determinedOutput(po.getClassroomRecordHistoryUseNumber()));
                    rank.setTeachingWareFollowedUseNumber(determinedOutput(po.getCourseWareFollowedUseNumber()));
                    rank.setTeachingWareHistoryUseNumber(determinedOutput(po.getCourseWareHistoryUseNumber()));
                    rank.setTeachingPlanFollowedUseNumber(determinedOutput(po.getTeachingPlanFollowedUseNumber()));
                    rank.setTeachingPlanHistoryUseNumber(determinedOutput(po.getTeachingPlanHistoryUseNumber()));
                    rank.setTeachingMaterialFollowedUseNumber(determinedOutput(po.getTeachMaterialFollowedUseNumber()));
                    rank.setTeachingMaterialHistoryUseNumber(determinedOutput(po.getTeachMaterialHistoryUseNumber()));
                    rank.setAssigmentFollowedUseNumber(determinedOutput(po.getAssignmentFollowedUseNumber()));
                    rank.setAssigmentHistoryUseNumber(determinedOutput(po.getAssignmentHistoryUseNumber()));
                    return rank;
                })
                .sorted(Comparator.comparing(comparing()))
                .collect(Collectors.toList());
    }

    /**
     * 附件四：获取教师同步教研环节资源使用个数排名
     *
     * @param pos the pos
     * @return the teacher research usage rank
     */
    static List<TeacherResearchUsageNumberRank> getTeacherResearchUsageRank(List<TeacherTeachingActivityResearchResourceUsageDetailPO> pos) {
        return pos.parallelStream()
                .map(po -> {
                    TeacherResearchUsageNumberRank rank = new TeacherResearchUsageNumberRank();
                    fillCommonRankInfo(po, rank);
                    rank.setTotal(determinedOutput(po.getResourceUseNumber()));
                    rank.setResearchFollowedUseNumber(determinedOutput(po.getRecordFollowedUseNumber()));
                    rank.setResearchHistoryUseNumber(determinedOutput(po.getRecordHistoryUseNumber()));
                    rank.setResearchWareFollowedUseNumber(determinedOutput(po.getWareFollowedUseNumber()));
                    rank.setResearchWareHistoryUseNumber(determinedOutput(po.getWareHistoryUseNumber()));
                    rank.setResearchMaterialFollowedUseNumber(determinedOutput(po.getMaterialFollowedUseNumber()));
                    rank.setResearchMaterialHistoryUseNumber(determinedOutput(po.getMaterialHistoryUseNumber()));
                    return rank;
                })
                .sorted(Comparator.comparing(comparing()))
                .collect(Collectors.toList());
    }

    /**
     * 附件五：获取教师学生活动环节资源使用个数排名
     *
     * @param pos the pos
     * @return the teacher student activity usage rank
     */
    static List<TeacherStudentActivityUsageNumberRank> getTeacherStudentActivityUsageRank(List<TeacherTeachingActivityStudentResourceUsageDetailPO> pos) {
        return pos.parallelStream()
                .map(po -> {
                    TeacherStudentActivityUsageNumberRank rank = new TeacherStudentActivityUsageNumberRank();
                    fillCommonRankInfo(po, rank);
                    rank.setTotal(determinedOutput(po.getResourceUseNumber()));
                    rank.setActivityFollowedUseNumber(determinedOutput(po.getRecordFollowedUseNumber()));
                    rank.setActivityHistoryUseNumber(determinedOutput(po.getRecordHistoryUseNumber()));
                    rank.setActivityPlanFollowedUseNumber(determinedOutput(po.getActivityPlanFollowedUseNumber()));
                    rank.setActivityPlanHistoryUseNumber(determinedOutput(po.getActivityPlanHistoryUseNumber()));
                    rank.setActivityMaterialFollowedUseNumber(determinedOutput(po.getMaterialFollowedUseNumber()));
                    rank.setActivityMaterialHistoryUseNumber(determinedOutput(po.getMaterialHistoryUseNumber()));
                    rank.setStudentExampleFollowedUseNumber(determinedOutput(po.getStudentSampleFollowedUseNumber()));
                    rank.setStudentExampleHistoryUseNumber(determinedOutput(po.getStudentSampleHistoryUseNumber()));
                    rank.setExtraCurricularFollowedUseNumber(determinedOutput(po.getExtracurricularExtensionFollowedUseNumber()));
                    rank.setExtraCurricularHistoryUseNumber(determinedOutput(po.getExtracurricularExtensionHistoryUseNumber()));
                    return rank;
                })
                .sorted(Comparator.comparing(comparing()))
                .collect(Collectors.toList());
    }

    /**
     * 附件六：获取教师同步测验环节资源使用个数排名
     *
     * @param pos the pos
     * @return the teacher exam usage rank
     */
    static List<TeacherExamUsageNumberRank> getTeacherExamUsageRank(List<TeacherTeachingActivityExamResourceUsageDetailPO> pos) {
        return pos.parallelStream()
                .map(po -> {
                    TeacherExamUsageNumberRank rank = new TeacherExamUsageNumberRank();
                    fillCommonRankInfo(po, rank);
                    rank.setTotal(determinedOutput(po.getResourceUseNumber()));
                    rank.setGeneralPaperFollowedUseNumber(determinedOutput(po.getGeneralPaperFollowedUseNumber()));
                    rank.setGeneralPaperHistoryUseNumber(determinedOutput(po.getGeneralPaperHistoryUseNumber()));
                    rank.setSecretPaperFollowedUseNumber(determinedOutput(po.getSecretPaperFollowedUseNumber()));
                    rank.setSecretPaperHistoryUseNumber(determinedOutput(po.getSecretPaperHistoryUseNumber()));
                    return rank;
                })
                .sorted(Comparator.comparing(comparing()))
                .collect(Collectors.toList());
    }

    /**
     * 附件七：截止本月，本学期教师同步资源使用率排名
     *
     * @param pos the pos
     * @return the teacher resource usage rate rank
     */
    static List<TeacherResourceUsageRateRank> getTeacherResourceUsageRateRank(List<TeacherTeachingActivityResourceUsageRatePO> pos) {
        return pos.parallelStream()
                .map(po -> {
                    TeacherResourceUsageRateRank rank = new TeacherResourceUsageRateRank();
                    fillCommonRankInfo(po, rank);
                    rank.setTotal(determinedOutput(po.getResourceUseRate()));
                    if (Objects.nonNull(po.getRoleIdentity()) && po.getRoleIdentity().equals(1)) {
                        rank.setPrepareLessonUseRate("-");
                        rank.setTeachingUseRate("-");
                        rank.setResearchUseRate("-");
                        rank.setStudentActivityUseRate("-");
                    } else {
                        rank.setPrepareLessonUseRate(NumberFormatUtil.formatPercent(po.getPrepareResourceUseRate(), "-"));
                        rank.setTeachingUseRate(NumberFormatUtil.formatPercent(po.getTeachingResourceUseRate(), "-"));
                        rank.setResearchUseRate(NumberFormatUtil.formatPercent(po.getResearchResourceUseRate(), "-"));
                        rank.setStudentActivityUseRate(NumberFormatUtil.formatPercent(po.getActivityResourceUseRate(), "-"));
                    }
                    rank.setExamUseRate(NumberFormatUtil.formatPercent(po.getExamResourceUseRate(), "-"));


                    rank.setTotalUseRate(NumberFormatUtil.formatPercent(po.getResourceUseRate(), "-"));
                    return rank;
                })
                .sorted(Comparator.comparing(comparing()))
                .collect(Collectors.toList());
    }

    /**
     * Fill common rank info teacher resource usage rate rank.
     *
     * @param po   the po
     * @param rank the rank
     */
    static void fillCommonRankInfo(CommonRankEntity po, CommonRankInfo rank) {
        rank.setRank(po.getRanking());
        rank.setTeacherName(po.getTeacherName());
        rank.setRoleIdentity(po.getRoleIdentity());
        if (Objects.nonNull(po.getRoleIdentity()) && po.getRoleIdentity().equals(1)) {
            rank.setSubject("-");
            rank.setTeacherName(rank.getTeacherName() + "(试卷保密员)");
        } else {
            rank.setSubject(Optional.ofNullable(po.getSubjectCode())
                                    .map(subject -> Arrays.stream(subject.split(","))
                                            .map(SubjectType::getByCode)
                                            .distinct()
                                            .sorted(Comparator.comparing(Enum::ordinal))
                                            .map(SubjectType::getName)
                                            .collect(Collectors.joining(",")))
                                    .orElse("-"));
        }
    }

    /**
     * Determined output string.
     *
     * @param value the value
     * @return the string
     */
    static String determinedOutput(Object value) {
        return Optional.ofNullable(value).map(String::valueOf).orElse("-");
    }

    /**
     * 构建自动合并单元格的表格(按分组合并)
     *
     * @param firstHeader the first header
     * @param groups      the groups
     * @param cols        the cols
     * @return the table builder
     */
    static Tables.TableBuilder getTableBuilder(String firstHeader, List<String> groups, List<String> cols) {
        List<List<String>> rowsHeader = Lists.newArrayList();
        List<String> row1 = new ArrayList<>();
        row1.add(firstHeader);
        for (String group : groups) {
            for (String ignored : cols) {
                row1.add(group);
            }
        }
        List<String> row2 = new ArrayList<>();
        row2.add(firstHeader);
        for (String ignored : groups) {
            row2.addAll(cols);
        }
        rowsHeader.add(row1);
        rowsHeader.add(row2);
        return getTableBuilder(rowsHeader);
    }

    /**
     * 构建自动合并单元格的表格
     *
     * @param rowsHeader the rows header
     * @return the table builder
     */
    static Tables.TableBuilder getTableBuilder(List<List<String>> rowsHeader) {
        MergeCellRule.MergeCellRuleBuilder builder = MergeCellRule.builder();
        ContinuousElementsUtil.calculateAndConvert(rowsHeader,
                                                   (ContinuousElementsUtil.ConvertConsumer) (start, end) ->
                                                           builder.map(MergeCellRule.Grid.of(start.getX(), start.getY()), MergeCellRule.Grid.of(end.getX(), end.getY())));


        Tables.TableBuilder tableBuilder = Tables.of().mergeRule(builder.build());

        // 表头1
        for (List<String> headers : rowsHeader) {
            Rows.RowBuilder rowBuilder = Rows.of().bgColor("4e70ee").textBold().textColor("ffffff").textFontSize(8).center();
            for (String header : headers) {
                rowBuilder.addCell(Cells.create(header));
            }
            tableBuilder.addRow(rowBuilder.create());
        }
        return tableBuilder;
    }

    /**
     * Comparing function.
     *
     * @return the function
     */
    static Function<CommonRankInfo, Integer> comparing() {
        return commonRankInfo -> Objects.isNull(commonRankInfo.getRank()) ? Integer.MAX_VALUE : commonRankInfo.getRank();
    }
}
